package cn.icanci.loopstack.ddk.admin.biz.service.impl;

import cn.icanci.loopstack.ddk.admin.biz.service.LockService;
import cn.icanci.loopstack.ddk.admin.biz.utils.EnvUtils;
import cn.icanci.loopstack.ddk.admin.dal.mapper.entity.LockDO;
import cn.icanci.loopstack.ddk.admin.dal.mapper.mapper.LockMapper;
import io.netty.util.internal.ThrowableUtil;

import java.util.Date;

import javax.annotation.Resource;

import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

/**
 * @author icanci
 * @since 1.0 Created in 2023/01/12 08:36
 */
@Service
public class LockServiceImpl implements LockService {

    private static final org.slf4j.Logger LOGGER  = LoggerFactory.getLogger(LockServiceImpl.class);

    @Resource
    private LockMapper                    lockMapper;

    private static final int              TIMEOUT = 3000;

    @Override
    public Long acquire(String key) {
        // 查询
        String env = EnvUtils.getEnv();
        LockDO oldLock = lockMapper.queryByResource(key, env);
        if (oldLock != null) {
            if (System.currentTimeMillis() - oldLock.getCreateTime().getTime() > TIMEOUT) {
                release(key, oldLock.getId());
            }
            return null;
        }

        try {
            LockDO lockDO = new LockDO();
            lockDO.setResource(key);
            lockDO.setDesc(key);
            lockDO.setEnv(env);
            lockDO.setCreateTime(new Date());
            lockMapper.insert(lockDO);
            return lockDO.getId();
        } catch (DuplicateKeyException ex) {
            LOGGER.warn("[LockService][acquire][DuplicateKeyException] lock acquire error:{}", ThrowableUtil.stackTraceToString(ex));
        } catch (Exception ex) {
            LOGGER.warn("[LockService][acquire][Exception] lock acquire error:{}", ThrowableUtil.stackTraceToString(ex));
        }
        return null;
    }

    @Override
    public boolean release(String key, Long lockId) {
        return lockMapper.delete(lockId, key, EnvUtils.getEnv()) > 0;
    }
}
